//
//  CS_ImportFromWIFIView.swift
//  NewSS
//
//  Created by 杨馥瑞 on 2021/9/6.
//

import UIKit

class CS_ImportFromWIFIView: UIView {
    
    private lazy var _maskButton: UIButton = _getMaskButton()
    private lazy var _contentView: CS_ImportFromWIFIContentView = _getContentView()
    private var _dismissComplete: (()->Void)?
    private let _contentViewHeight: CGFloat = kScale(334) + kSafeAreaBottom
    private let _animateDuration: TimeInterval = 0.3

    override init(frame: CGRect) {
        super.init(frame: frame)
        
        _commonInit()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // MARK: - 外部方法
    
    static func show(in containerView: UIView? = UIApplication.shared.keyWindow, dismissComplete: (()->Void)? = nil) {
        let importFromWIFIView = CS_ImportFromWIFIView(frame: containerView?.bounds ?? UIScreen.main.bounds)
        importFromWIFIView.show(in: containerView, dismissComplete: dismissComplete)
    }
    
    func show(in containerView: UIView? = UIApplication.shared.keyWindow, dismissComplete: (()->Void)? = nil) {
        guard let containerView = containerView else { return }
        _dismissComplete = dismissComplete
        containerView.addSubview(self)
        
        UIView.animate(withDuration: _animateDuration) {
            self._contentView.frame.origin.y = self.bounds.size.height - self._contentViewHeight
        }
    }
    
    func dismiss() {
        
        let alert = LGAlertView(title: "提示", message: "关闭页面后无法导入歌曲", style: .alert, buttonTitles: ["确定"], cancelButtonTitle: "取消", destructiveButtonTitle: nil) { _, _, _ in
            _dismiss()
        } cancelHandler: { _ in
            
        } destructiveHandler: { _ in
            
        }
        alert.tintColor = .mainColor
        alert.showAnimated()
        
        func _dismiss() {
            _maskButton.isUserInteractionEnabled = false
            UIView.animate(withDuration: _animateDuration) {
                self._contentView.frame.origin.y = self.bounds.size.height
            } completion: { _ in
                self._dismissComplete?()
                self.removeFromSuperview()
            }
        }
        
    }
    
    // MARK: - 事件
    
    @objc private func _maskButtonClick() {
        dismiss()
    }
    
    // MARK: - 私有方法
    
    private func _commonInit() {
        addSubview(_maskButton)
        addSubview(_contentView)
        
        _maskButton.frame = bounds
        _contentView.frame = CGRect(x: 0, y: height, width: width, height: _contentViewHeight)
        
        _initListener()
    }
    
    private func _initListener() {
        _contentView.cancelClickBlock = { [weak self] in
            self?.dismiss()
        }
    }
    
    private func _getMaskButton() -> UIButton {
        let button = UIButton(type: .custom)
        button.setBackgroundColor(.black.withAlphaComponent(0.4), forState: .normal)
        button.addTarget(self, action: #selector(_maskButtonClick), for: .touchUpInside)
        return button
    }
    
    private func _getContentView() -> CS_ImportFromWIFIContentView {
        let view = CS_ImportFromWIFIContentView()
        return view
    }

}

private protocol CS_ImportFromWIFIContentViewDelegate: NSObjectProtocol {
    func importFromWifiContentView(_ wifiContentView: CS_ImportFromWIFIContentView, receiveFileIsValid file: String) -> Bool
}

private extension CS_ImportFromWIFIContentViewDelegate {
    func importFromWifiContentView(_ wifiContentView: CS_ImportFromWIFIContentView, receiveFileIsValid file: String) -> Bool { return false }
}

private class CS_ImportFromWIFIContentView: UIView, CS_WifiManagerDelegate {
    
    enum Status: CaseIterable {
        case noWIFI             // 没有连接 wifi
        case ready              // 就绪状态
        case transfering        // 传输中
        case transferSuccess    // 传输成功
        case transferFailure    // 传输失败
    }
    
    var cancelClickBlock: (()->Void)?
    weak var delegate: CS_ImportFromWIFIContentViewDelegate?
    
    private lazy var _statusImageView: UIImageView = _getStatusImageView()
    private lazy var _statusLabel: UILabel = _getStatusLabel()
    private lazy var _guideLabel: UILabel = _getGuideLabel()
    private lazy var _ipAddressLabel: UILabel = _getIPAddressLabel()
    private lazy var _tipsButton: UIButton = _getTipsButton()
    private lazy var _cancelButton: UIButton = _getCancelButton()
    private var _status: Status = .noWIFI
    private var _wifiManager: CS_WifiManager?
    private var _uploadingItems: [CS_WifiTransferFileItem] = [CS_WifiTransferFileItem]()
    private var _uploadSuccessItems: [CS_WifiTransferFileItem] = [CS_WifiTransferFileItem]()
    private var _fileManager: CS_ImportMusicFromWifiFileManager = CS_ImportMusicFromWifiFileManager()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        _commonInit()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // MARK: - 外部方法
    
    // MARK: - 事件
    
    @objc private func _cancelButtonClick() {
        cancelClickBlock?()
    }
    
    @objc private func _networkStatusChanged() {
        _refreshNetworkStatus()
    }
    
    // MARK: - CS_WifiManagerDelegate
    
    func wifiManagerDidStart(_ manager: CS_WifiManager) {
        let displayUrl = manager.displayURL
        if displayUrl.count > 0 {
            _ipAddressLabel.text = displayUrl
            _changeStatusTo(.ready)
        }
        else {
            _changeStatusTo(.noWIFI)
        }
    }
    
    func wifiManager(_ manager: CS_WifiManager, beginReceive file: CS_WifiTransferFileItem) {
        // 如果已在下载队列中，则删除使用新的
        _uploadingItems = _uploadingItems.filter { $0 != file }
        _uploadingItems.append(file)
        _changeStatusTo(.transfering)
    }
    
    func wifiManager(_ manager: CS_WifiManager, endReceive file: CS_WifiTransferFileItem, isSuccess: Bool) {
        if isSuccess {
            _uploadSuccessItems = _uploadSuccessItems.filter { $0 != file }
            _uploadingItems = _uploadingItems.filter { $0 != file }
            _uploadSuccessItems.append(file)
            _changeStatusTo(.transferSuccess)
        }
        else {
            _changeStatusTo(.transferFailure)
        }
        
        guard isSuccess else { return }
        var needSaveToDB = false
        let fileExit = _fileManager.desPathExitSameFileName(file.fileName)
        
        if !fileExit {
            let isValid = delegate?.importFromWifiContentView(self, receiveFileIsValid: file.filePath) ?? false
            // furui dummy 暂时放开限制
//            if !isValid { return }
            if _fileManager.moveFile(file.filePath, toDesPathWithName: file.fileName) {
                needSaveToDB = true
            }
        }
        else {
            // 文件已存在，又收到这个文件。重复写一次，防止删除表，但是文件没有删除，极端case
            needSaveToDB = true
        }
        
        if needSaveToDB {
            // 将文件的索引构建成模型存到数据库
            _fileManager.saveFileNameToDB(file.fileName)
        }
    }
    
    // MARK: - 私有方法
    
    private func _commonInit() {
        _initUI()
        _initListener()
        
        _refreshNetworkStatus()
    }
    
    private func _initUI() {
        backgroundColor = .white
        
        addSubview(_statusImageView)
        addSubview(_statusLabel)
        addSubview(_guideLabel)
        addSubview(_ipAddressLabel)
        addSubview(_tipsButton)
        addSubview(_cancelButton)
        
        _statusImageView.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.width.height.equalTo(kScale(37))
            make.top.equalTo(kScale(49.5))
        }
        
        _statusLabel.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.top.equalTo(_statusImageView.snp.bottom).offset(kScale(15))
        }
        
        _guideLabel.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.top.equalTo(_statusLabel.snp.bottom).offset(kScale(23))
        }
        
        _ipAddressLabel.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.top.equalTo(_guideLabel.snp.bottom).offset(kScale(11))
        }
        
        _tipsButton.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.bottom.equalTo(_cancelButton.snp.top).offset(-kScale(27))
            make.width.equalToSuperview().offset(-kScale(2*10))
        }
        
        _cancelButton.snp.makeConstraints { make in
            make.bottom.equalTo(-kScale(36))
            make.centerX.equalToSuperview()
            make.width.equalTo(kScale(315))
            make.height.equalTo(kScale(49))
        }
        
        _changeStatusTo(.ready)
    
    }
    
    private func _initListener() {
        NotificationCenter.default.addObserver(self, selector: #selector(_networkStatusChanged), name: Notification.Name("HttpManager.Network.Status.Changed"), object: nil)
    }
    
    private func _changeStatusTo(_ newStatus: Status) {
        switch newStatus {
        case .noWIFI:
            _statusImageView.image = UIImage(named: "room_music_wifi_invalid")
            _statusLabel.text = "未搜索到WI-FI"
            _guideLabel.text = "手机与电脑连接同一WI-FI后\n可通过电脑导入音乐"
            _guideLabel.textColor = .hexString("#19bbb7")
            _ipAddressLabel.isHidden = true
            _tipsButton.isHidden = true
            _statusImageView.cs_stopRotationAnimation()
        case .ready:
            _statusImageView.image = UIImage(named: "room_music_wifi_valid")
            _statusLabel.text = "已连接"
            _guideLabel.text = "在电脑浏览器中输入以下地址"
            _guideLabel.textColor = .colorT1
            _ipAddressLabel.isHidden = false
            _tipsButton.isHidden = false
            _statusImageView.cs_stopRotationAnimation()
        case .transfering:
            _statusImageView.image = UIImage(named: "room_music_wifi_loading")
            _statusLabel.text = "导入中..."
            _guideLabel.text = _uploadingItems.last?.fileName ?? ""
            _guideLabel.textColor = .colorT1
            _ipAddressLabel.isHidden = true
            _tipsButton.isHidden = false
            _tipsButton.setTitle("上传过程中请勿关闭此页", for: .normal)
            _statusImageView.cs_startRotationAnimation()
        case .transferSuccess:
            _statusImageView.image = UIImage(named: "room_music_wifi_loading_success")
            _statusLabel.text = "导入成功"
            _guideLabel.text = _uploadSuccessItems.last?.fileName ?? ""
            _guideLabel.textColor = .colorT1
            _ipAddressLabel.isHidden = true
            _tipsButton.isHidden = false
            _tipsButton.setTitle("上传过程中请勿关闭此页", for: .normal)
            _statusImageView.cs_stopRotationAnimation()
        default:
            break
        }
    }
    
    /// 刷新网络状态
    private func _refreshNetworkStatus() {
        // 未连接wifi
        if HttpManager.shared.netowrkStatus() != .reachable(.ethernetOrWiFi) {
            _wifiManager?.stop()
            _wifiManager = nil
            _changeStatusTo(.noWIFI)
        }
        else {
            _wifiManager = CS_WifiManager()
            _wifiManager?.delegate = self
            _wifiManager?.start()
        }
    }
    
    // MARK: - 懒加载
    
    private func _getCancelButton() -> UIButton {
        let button = UIButton(type: .custom)
        button.addTarget(self, action: #selector(_cancelButtonClick), for: .touchUpInside)
        button.layer.cornerRadius = kScale(24.5)
        button.layer.borderColor = UIColor.colorT3.cgColor
        button.layer.borderWidth = 1
        button.layer.masksToBounds = true
        button.setTitle("取消", for: .normal)
        button.titleLabel?.font = kFont(kPingFangSCSemibold, 16)
        button.setTitleColor(.colorT2, for: .normal)
        return button
    }
    
    private func _getStatusImageView() -> UIImageView {
        let imageView = UIImageView()
        imageView.image = UIImage(named: "room_music_wifi_invalid")
        return imageView
    }
    
    private func _getStatusLabel() -> UILabel {
        let label = UILabel()
        label.text = "未搜索到WI-FI"
        label.font = kFont(kPingFangSCSemibold, 14)
        label.textAlignment = .center
        label.textColor = .colorT1
        return label
    }
    
    private func _getGuideLabel() -> UILabel {
        let label = UILabel()
        label.text = "手机与电脑连接同一WI-FI后\n可通过电脑导入音乐"
        label.font = kFont(kPingFangSCSemibold, 14)
        label.numberOfLines = 0
        label.textColor = .hexString("#19bbb7")
        label.textAlignment = .center
        return label
    }
    
    private func _getIPAddressLabel() -> UILabel {
        let label = UILabel()
        label.font = kFont(kPingFangSCSemibold, 18)
        label.textColor = .hexString("#2f6eff")
        label.textAlignment = .center
        return label
    }
    
    private func _getTipsButton() -> UIButton {
        let button = UIButton(type: .custom)
        button.isUserInteractionEnabled = false
        button.setImage(UIImage(named: "room_music_wifi_attention"), for: .normal)
        button.setTitle("手机与电脑连接同一Wi-Fi后，可通过电脑导入音乐", for: .normal)
        button.setTitleColor(.colorT3, for: .normal)
        button.titleLabel?.font = kFont(kPingFangSCSemibold, 12)
        button.titleEdgeInsets = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 0)
        button.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 5)
        return button
    }
    
}

private struct CS_ImportMusicFromWifiFileManager {
    
    func desPathExitSameFileName(_ filename: String) -> Bool {
        return CS_MusicWifiFileStorage.shared.isAlreadyExit(filename)
    }
    
    func moveFile(_ filePath: String, toDesPathWithName filename: String) -> Bool {
        return CS_MusicWifiFileStorage.shared.moveFilePath(filePath, toDesPathWithName: filename)
    }
    
    func saveFileNameToDB(_ fileName: String) {
        func createMusicModel(byFilename filename: String) -> CS_MusicModel {
            let result = CS_MusicModel()
            result.isLocal = true
            result.musicName = fileName
            result.audioUrl = CS_MusicWifiFileStorage.shared.getStoreRelativePath().appendingPathComponent(fileName)
            let path = CS_MusicWifiFileStorage.shared.getStorePath().appendingPathComponent(fileName)
            result.singerName = singerNameForPath(path)
            result.identifier = result.getIdentifier()
            return result
        }
        // 存库
        CS_MusicManager.shared.addMusic(createMusicModel(byFilename: fileName))
    }
    
    func singerNameForPath(_ path: String) -> String {
        let fileURL = NSURL(fileURLWithPath: path)
        var fileID: AudioFileID? = nil
        var error: OSStatus = noErr
        
        let cfFileURL = fileURL as CFURL
        error = AudioFileOpenURL(cfFileURL, .readPermission, .zero, &fileID)
        if error != noErr {
            print("AudioFileOpenURL failed")
        }
        
        if fileID != nil {
            var id3DataSize: UInt32 = 0
            error = AudioFileGetPropertyInfo(fileID!, kAudioFilePropertyID3Tag, &id3DataSize, .none)
            if error != noErr {
                print("AudioFileGetPropertyInfo failed for ID3 tag")
            }
            
            var piDict: NSDictionary? = nil
            var piDataSize: UInt32 = UInt32(MemoryLayout.size(ofValue: piDict))
            error = AudioFileGetProperty(fileID!, kAudioFilePropertyInfoDictionary, &piDataSize, &piDict)
            if error != noErr {
                print("AudioFileGetProperty failed for property info dictionary")
            }
            
            let artist = piDict?.object(forKey: NSString(utf8String: kAFInfoDictionary_Artist) ?? "") as? String ?? ""
            if !artist.isEmpty {
                return artist
            }
            
            if let url = URL(string: path) {
                let audioAsset = AVURLAsset(url: url)
                let artist = AVMetadataItem.metadataItems(
                    from: audioAsset.commonMetadata,
                    withKey: AVMetadataKey.commonKeyArtist,
                    keySpace: .common
                ).first?.value as? String ?? ""
                return artist
            }
        }
        
        return ""
    }
    
}
